package com.pro.staffmanage.service;

import com.pro.staffmanage.mapper.RoleMapper;
import com.pro.staffmanage.mapper.UserMapper;
import com.pro.staffmanage.pojo.Role;
import com.pro.staffmanage.pojo.User;
import com.pro.staffmanage.utils.PasswordUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsPasswordService;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;

import java.security.InvalidAlgorithmParameterException;
import java.util.*;

@Service
public class UserService implements UserDetailsService, UserDetailsPasswordService {

    private UserMapper userMapper;
    private RoleMapper roleMapper;

    @Autowired
    public UserService(UserMapper userMapper, RoleMapper roleMapper){
        this.userMapper = userMapper;
        this.roleMapper = roleMapper;
    }

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        User userDetails = userMapper.loadUserByUsername(username);
        //  将用户以及他的权限绑定在一起
        if (ObjectUtils.isEmpty(userDetails)){
            throw new UsernameNotFoundException("用户名未注册!");
        }
        userDetails.setAuthorities(getAuthorities(userDetails.getId()));
        return userDetails;
    }

    private Set<GrantedAuthority> getAuthorities(int id){
        return userMapper.getAuthorities(id);
    }

    public List<User> queryAllUser(){
        return userMapper.queryAllUser();
    }

    public User queryUserById(Integer id){
        return userMapper.queryUserById(id);
    }

    public Integer addUser(User user){
        user.setAuthorities(new HashSet<GrantedAuthority>(){
            {
                add(roleMapper.queryRoleById(1));
            }
        });
        user.setPassword(PasswordUtil.getPassword(user.getPassword()));
        System.out.println(user);
        int cnt = userMapper.addUser(user);
        for (GrantedAuthority authority : user.getAuthorities()) {
            userMapper.addAuthorities(userMapper.loadUserByUsername(user.getUsername()).getId()
                    , ((Role)authority).getId());
        }
        return cnt;
    }

    //  用户自行更新数据时用, 此方法会用在controller中
    public Integer updateUser(User user) throws InvalidAlgorithmParameterException {
        //  noop代表明文
        //  bcrypt代表密文
        //  若一个密码开头既没有{noop}也没有{bcrypt}, 则说明这个密码被更新了需要加密码序列
        if (ObjectUtils.isEmpty(user)) {
            return 0;
        }
        //  检测密码是否属于指定算法中的密文, 不属于则说明用户更新了密码
        if (!PasswordUtil.isCipherText(user.getPassword())){
            user.setPassword(PasswordUtil.getPassword(user.getPassword()));
        }
        user.getAuthorities().forEach(
                item -> userMapper.updateAuthorities(
                            userMapper.loadUserByUsername(user.getUsername()).getId(), ((Role)item).getId())
        );
        return userMapper.updateUser(user);
    }

    public Integer deleteUser(Integer id){
        return userMapper.deleteUser(id);
    }

    //  自动更新密码: 上面的更新用户是用户去修改个人信息, 这里是对用户原密码进行算法更新
    //  在老版SpringSecurity中, 他会在WebSecurityConfigurerApdater中把认证成功的用户传给参数: UserDetails user
    @Override
    public UserDetails updatePassword(UserDetails user, String newPassword) {
        if (userMapper.updatePassword(user.getUsername(),newPassword)>0){
            ((User) user).setPassword(newPassword);
        }
        return user;
    }
}
